package com.quan.system.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.quan.commons.constant.CommonsConstant;
import com.quan.commons.core.MyBaseServiceImpl;
import com.quan.commons.utils.PageUtils;
import com.quan.commons.utils.SchedulerUtils;
import com.quan.system.commons.vo.SysSchedulerVo;
import com.quan.system.entity.SysScheduler;
import com.quan.system.mapper.SysSchedulerMapper;
import com.quan.system.service.SysSchedulerService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


@Slf4j
@Service
public class SysSchedulerServiceImpl extends MyBaseServiceImpl<SysSchedulerMapper, SysScheduler> implements SysSchedulerService {

    @Autowired
    private SysSchedulerMapper mapper;

    @Autowired
    private SchedulerUtils schedulerUtils;

    @Override
    public boolean deleteByIds(Collection<? extends Serializable> idList) {
        // 先把定时任务删除
        Collection<SysScheduler> list = super.listByIds(idList);
        list.forEach(item -> {
            try {
                this.schedulerUtils.deleteJob(item.getJobName(), item.getJobGroup());
            } catch (SchedulerException e) {
                e.printStackTrace();
            }
        });

        return super.removeByIds(idList);
    }

    @Override
    public List<SysSchedulerVo> queryList(PageUtils pageUtils, SysSchedulerVo vo) {
        QueryWrapper<SysScheduler> queryWrapper = new QueryWrapper<SysScheduler>(vo);

        List<SysScheduler> list = super.list(pageUtils, queryWrapper);
        List<SysSchedulerVo> collect = list.stream().map(item -> {
            SysSchedulerVo bean = new SysSchedulerVo();
            BeanUtils.copyProperties(item, bean);
            return bean;
        }).collect(Collectors.toList());

        return collect;
    }

    @Override
    public PageUtils queryPage(PageUtils pageUtils, SysSchedulerVo vo) {
        QueryWrapper<SysScheduler> queryWrapper = new QueryWrapper<SysScheduler>(vo);

        if (StringUtils.isNotBlank(vo.getKeyword())) {
            queryWrapper.and(w -> {
                w.like("job_name", vo.getKeyword());
            });
        }

        final IPage<SysScheduler> page = super.selectPage(pageUtils, queryWrapper);

        PageUtils ps = new PageUtils(page);

        final List<SysScheduler> records = page.getRecords();

        final List<SysScheduler> collect = records.stream().map((item) -> {
            SysSchedulerVo bean = new SysSchedulerVo();
            BeanUtils.copyProperties(item, bean);
            return bean;
        }).collect(Collectors.toList());

        ps.setRecords(collect);
        return ps;
    }

    @Override
    public boolean startJob(SysSchedulerVo vo) throws ClassNotFoundException, SchedulerException {
        if (StringUtils.isBlank(vo.getJobStatus())) {
            vo.setJobStatus(CommonsConstant.SchedulerStatus.RUNNING.getName());
        }
        if (StringUtils.isBlank(vo.getJobGroup())) {
            vo.setJobGroup(Scheduler.DEFAULT_GROUP);
        }

        // 先把旧的定时任务删除
        QueryWrapper<SysScheduler> queryWrapper = new QueryWrapper<SysScheduler>();
        queryWrapper.eq("job_name", vo.getJobName());
        List<SysScheduler> list = super.list(queryWrapper);
        if (null != list && !list.isEmpty()) {
            list.forEach(item -> {
                try {
                    this.schedulerUtils.deleteJob(item.getJobName(), item.getJobGroup());
                } catch (SchedulerException e) {
                    e.printStackTrace();
                }
                super.removeById(item.getId());
            });
        }

        // 将JSON字符串参数转换成Map保存到Scheduler JobDataMap
        if(null != vo.getJobDataMap()) {
            Map<String, Object> jobMapData = JSONObject.parseObject(vo.getJobParams());
            vo.setJobDataMap(jobMapData);
        }


        boolean flag = super.save(vo);
        if (flag) {
            // 新建定时任务
            this.schedulerUtils.newJob(vo);

            // 任务为暂停状态
            if (vo.getJobStatus().equals(CommonsConstant.SchedulerStatus.PAUSE.getName())) {
                this.pauseJob(vo.getId(), vo.getJobName(), vo.getJobGroup());
            }
        }

        return flag;
    }

    @Override
    public boolean updateJob(SysSchedulerVo vo) throws ClassNotFoundException, SchedulerException {
        // 先把旧的定时任务删除
        SysScheduler oldJob = super.getById(vo.getId());
        this.schedulerUtils.deleteJob(oldJob.getJobName(), oldJob.getJobGroup());

        boolean flag = super.updateById(vo);
        if (flag) {
            // 重新新建定时任务
            this.schedulerUtils.newJob(vo);
        }

        return super.updateById(vo);
    }

    @Override
    public void deleteJobByName(String jobName) throws SchedulerException {
        this.deleteJobByName(jobName, Scheduler.DEFAULT_GROUP);
    }

    @Override
    public void deleteJobByName(String jobName, String jobGroup) {
        QueryWrapper<SysScheduler> queryWrapper = new QueryWrapper<SysScheduler>();
        queryWrapper.eq("job_name", jobName).eq("job_group", jobGroup);
        List<SysScheduler> list = super.list(queryWrapper);

        if (null != list && !list.isEmpty()) {
            List<Serializable> delIds = new ArrayList<Serializable>();
            list.forEach(item -> {
                delIds.add(item.getId());
                try {
                    this.schedulerUtils.deleteJob(item.getJobName(), item.getJobGroup());
                } catch (SchedulerException e) {
                    e.printStackTrace();
                }
            });
            super.removeByIds(delIds);
        }

    }

    @Transactional
    @Override
    public void pauseJob(Long id, String jobName, String jobGroup) throws SchedulerException {
        this.schedulerUtils.pauseJob(jobName, jobGroup);
        this.changeStatus(id, CommonsConstant.SchedulerStatus.PAUSE.getName());
    }

    @Transactional
    @Override
    public void resumeJob(Long id, String jobName, String jobGroup) throws SchedulerException {
        this.schedulerUtils.resumeJob(jobName, jobGroup);
        this.changeStatus(id, CommonsConstant.SchedulerStatus.RUNNING.getName());
    }

    @Override
    public void triggerJob(Long id, String jobName, String jobGroup) throws SchedulerException {
        this.schedulerUtils.triggerJob(jobName, jobGroup);
    }

    @Override
    public void changeStatus(Long id, String jobStatus) {
        SysScheduler entity = new SysScheduler();
        entity.setId(id);
        entity.setJobStatus(jobStatus);
        super.updateById(entity);
    }
}